<template>
  <div class="homeMapContainer">
    <main-map
      class="mapComponents"
      ref="mainmapDom"
      @map-darw-click="mapDarwClick"
      @map-home-ctrl="mapHomeCtrl"
      @get-result-list="getResultList"
      @open-filter="openFilter"
      @open-info-window="openInfoWindow"
      @close-user-dialog="closeUserDialog"
      @close-dialog="closeDialog"
      :layer-list-data="layerListDataCopy"
    />
    <div class="mapCtlDom">
      <DialogGis
        class="mapCtlDomItem"
        style="left:0.5rem;top:0.2rem;position: absolute;"
        @callback-data="handleGisData"
        @click-heat="handleHeat"
        @map-type="handleMapType"
        @callback-cluster-data="callbackClusterData"
        @now-layer-data="nowLayerData"
        @to-detail="toDetail"
        :layer-list-data="layerListData"
      />
      <div class="heat mapCtlDomItem" v-if="heatShow">
        <TimeLineDialog
          @close="heatShow = false"
          @time-interval="timeInterval"
          :heat-data="heatData"
          :heat-key="heatKey"
          :layer-name="layerName"
        />
      </div>
      <div class="search-container mapCtlDomItem">
        <SearchDialog
          ref="searchDialogDom"
          class="search-dialog"
          @search-dialog-click="searchDialogClick"
          @callback="handleSearchData"
          @search-content="handleSearchContent"
          :layer-list-data="layerListDataCopy"
          :layer-search-list="layerSearchList"
          :result-list="resultList"
        />
      </div>
      <LocationDialog class="mapCtlDomItem locationDialog" @handle-area-select="handleAreaSelect" />
      <VideoDialog class="mapCtlDomItem videoDialog" v-if="videoShow" @close="handleShow" :url="playUrl" />
      <DetailDialog
        v-if="detailShow"
        ref="dialogDetailDom"
        class="mapCtlDomItem detailDialog"
        @close-detail="closeUserCenterDialog"
        :layer-id="layerId"
        :params-data="elementData"
        :title="detailTitle"
        @play-video="playVideo"
      />
      <DialogUserData
        ref="dialogUserDataDom"
        class="mapCtlDomItem userDataDialog"
        v-if="showUserDataDialog"
        :layer-id="Number(layerId)"
        :params-data="elementData"
        :title="detailTitle"
        @close-user-dialog="closeUserDialog"
      />
      <DialogFilter
        v-if="drawData"
        ref="dialogFilterDom"
        class="mapCtlDomItem filterDataDialog"
        @delect-draw="delectDraw"
        @selected-layers="selectedLayers"
        @close-dialog="closeDialog"
        :layer-list-data="layerListDataCopy"
        :draw-data="drawData"
      />
    </div>
    <img v-if="showLoading" :src="iconList.loadingGif" class="loading" alt="">
  </div>
</template>

<script lang="ts" setup>
import DialogGis from '../../components/Dialog/DialogGis.vue'
import TimeLineDialog from '../../components/Dialog/DialogTimeline.vue'
import SearchDialog from '../../components/Dialog/DialogSearch.vue'
import LocationDialog from '../../components/Dialog/DialogLocation.vue'
import VideoDialog from '../../components/Dialog/DialogVideo.vue'
import DialogUserData from '../../components/Dialog/DialogUserData.vue'
import DialogFilter from '../../components/Dialog/DialogFilter.vue'
import filterIcon from '@/assets/dialog/search_filter.png'
import DetailDialog from '@/components/Dialog/DialogWarnInfo.vue'
import Request from '@/utils/request'
import loadingGif from '@/assets/dialog/loading.gif'
// import DialogForm from '../../components/Dialog/DialogForm.vue'
import { updateElement, getMapList, elementSearchList, queryDrawList, findUintById } from '../../api/mapData'
import { ref, nextTick, reactive } from 'vue'
import { ElMessage } from 'element-plus'
import { useStore } from '@/store'
import { queryInfoById } from '@/api/mapConfig'
const iconList = reactive({
  loadingGif: loadingGif,
  filterIcon: filterIcon
})
const heatShow = ref(false) // 是否显示热力图时间轴
const layerListData = ref([] as any)
const layerListDataCopy = ref([] as any)
const layerSearchList = ref([] as any)
const resultList = ref([] as any) // 查询返回列表数据
const store = useStore()
const currentAreaCode = ref('') // 当前选中行政区划code 默认最大级code
const videoShow = ref(false) // 是否显示播放器
const showUserDataDialog = ref(false) // 是否显示详情弹窗
const searchDialogDom = ref() // 搜索弹窗dom
const dialogUserDataDom = ref() // 详情弹窗dom
const heatData = ref([] as any) // 热力图数据，用于时间轴
const heatKey = ref() // 热力图绑定关键字
const layerName = ref('')
const nowHeatLayerId = ref('') // 当前选中热力图的id
const mainmapDom = ref() // 地图组件dom
const dialogFilterDom = ref() // 标绘图层操作弹窗
const drawData:any = ref() // 当前选中标绘区域信息
const detailShow = ref(false) // 展示详情 由下发字段控制中心显示 还是点位显示
const layerId = ref('' as any)
const layerData:any = ref({}) // 已获取的图层数据
const elementData:any = ref({}) // 点击弹窗详情信息
const showLoading = ref(true) // 是否显示加载动画
const minIndex = ref(2) // 弹窗的最低默认层级
const pz_list = reactive({}) // 各个图层的配置信息
const playUrl = ref('')
const detailTitle = ref('')
const playVideo = (url:any) => {
  playUrl.value = url
  videoShow.value = true
}
const handleShow = () => {
  videoShow.value = false
}

// 地图点击标绘触发
const mapDarwClick = () => {
  if (searchDialogDom.value) {
    searchDialogDom.value.closeSearchDialog()
  }
}
// 搜索弹窗显示按钮点击触发
const searchDialogClick = () => {
  if (mainmapDom.value) {
    mainmapDom.value?.closeDrawDialog()
  }
}
// 获取指定图层数据
const getMapDataByUrl = (url:string, params?:any) => {
  return Request({
    url: url,
    method: 'GET',
    params
  })
}
// 点击聚合开关
const callbackClusterData = (item:any) => {
  heatShow.value = false
  let config:any = {}
  if (pz_list && pz_list[item.elementType] && pz_list[item.elementType].collectDO) {
    config = JSON.parse(pz_list[item.elementType].collectDO.content)
  }
  mainmapDom.value?.clusterSwitch(item.elementType, item.showCluster, config)
}

// 当前图层选中状态
const nowLayerData = (resData:any) => {
  const allLayerList:any = []
  const res = JSON.parse(JSON.stringify(resData))

  if (res && res.length > 0) {
    res.forEach((item:any) => {
      if (item.children && item.children.length > 0) {
        item.children.forEach((element:any) => {
          allLayerList.push(element)
        })
      }
      if (item.children) {
        delete item.children
      }
      if (item.list) {
        delete item.list
      }
      allLayerList.push(item)
    })
  }
  layerListDataCopy.value = allLayerList
}
// 处理地图显示隐藏结果
const handleGisData = async (ids:string, isVisible:boolean, itemList:any) => {
  const param:any = {
    ids,
    isShow: isVisible ? 1 : 0
  }
  // 更新图层操作记录
  updateElement(param)
  heatShow.value = false
  const params = {
    xzqhdm: currentAreaCode.value.replace(/(0+)$/g, '')
  }
  // 控制地图打点
  if (itemList) {
    if (isVisible) {
      itemList.forEach((el:any) => {
        if (el.apiDO && el.apiDO.url && el.apiDO.url !== 'null') {
          findUintById(el.elementId).then(
            (pz_res:any) => {
              pz_list[el.elementType] = pz_res
              getMapDataByUrl(el.apiDO.url, params).then((res:any) => {
                let ifReturn = false
                if (layerListDataCopy.value) {
                  for (let i = 0; i < layerListDataCopy.value.length; i++) {
                    if (layerListDataCopy.value[i].elementType === el.elementType) {
                      if (!layerListDataCopy.value[i].visible) {
                        ifReturn = true
                        break
                      }
                    }
                  }
                }
                if (!ifReturn) {
                  layerData.value[el.elementType] = res
                  try {
                    if (pz_res.heatmapDO && !(pz_res.heatmapDO && pz_res.heatmapDO.enabled === 1)) { // heatShow 是否支持时间轴？？？
                      const fieldNameEn = JSON.parse(pz_res.heatmapDO.config).timeAccordance || 'bjsj'
                      try {
                        if (res && res.length > 0) {
                          res.forEach((sitem:any) => {
                            if (sitem[fieldNameEn]) {
                              sitem.parseDate = Date.parse(sitem[fieldNameEn].split('T')[0])
                            }
                          })
                        }
                        mainmapDom.value?.addFeaturLayer(el, res, { icon: el.elementType }, pz_res)
                      } catch (error) {
                        console.log(error)
                      }
                    } else {
                      try {
                        mainmapDom.value?.addFeaturLayer(el, res, { icon: el.elementType }, pz_res)
                      } catch (error) {
                        console.log(error)
                      }
                    }
                  } catch (error) {
                    console.log(error)
                  }
                  // 展示热力
                  if (pz_res.showType === 1) {
                    el.heat = pz_res.heat = true
                    el.showCluster = pz_res.showCluster = !pz_res.heat
                    handleHeat(pz_res, true)
                  } else if (pz_res.showType === 2) { // 展示聚合
                    el.showCluster = pz_res.showCluster = true
                    el.heat = pz_res.heat = !pz_res.showCluster
                    callbackClusterData(pz_res)
                  }
                }
              })
            })
        }
      })
    } else {
      itemList.forEach((el:any) => {
        try {
          mainmapDom.value?.clearLayer(el.elementType)
        } catch (error) {
          console.log(error)
        }
      })
    }
  }
}
// 是否显示热力图
const handleHeat = async (item:any, isShow:boolean) => {
  layerName.value = item.elementName
  let config:any = {}
  if (pz_list && pz_list[item.elementType] && pz_list[item.elementType].heatmapDO) {
    config = JSON.parse(pz_list[item.elementType].heatmapDO.config)
  }
  mainmapDom.value?.heatmapSwitch(item.elementType, item.heat, config)
  if (isShow) {
    heatData.value = layerData.value[item.elementType]
    nowHeatLayerId.value = item.elementType
    heatShow.value = true
    if (config) {
      // 时间轴对应字段
      heatKey.value = config.timeAccordance || 'bjsj'
      // 判断是否支持时间轴播放
      if (config.isSupportTimeLine) {
        heatShow.value = false
      }
    } else {
      heatShow.value = false
    }
  } else {
    heatShow.value = false
  }
}
// 处理底图选择结果
const handleMapType = (ids:string, isVisible:boolean, layerList:any) => {
  const param:any = {
    ids,
    isShow: isVisible ? 1 : 0
  }
  // updateMapSelect(param)
  if (isVisible) {
    try {
      mainmapDom.value?.toggleBasemap(layerList[0].element_type)
    } catch (error) {
      console.log(error)
    }
  }
}

// 地图加载完毕
const mapHomeCtrl = async () => {
  showLoading.value = false
  const areaList = store.getters.getAreaList // 行政区划树结构
  currentAreaCode.value = areaList[0].code
  getMapListData(true)
  getDrawList()
}

// 获取图层列表
const getMapListData = async (firstLoad?:boolean) => {
  heatShow.value = false
  const res = await getMapList()
  layerListData.value = res

  const params = {
    xzqhdm: currentAreaCode.value.replace(/(0+)$/g, '')
  }
  // 首次初始化地图要素图层
  layerListData.value.forEach((item:any) => {
    const visible = !!Number(item.isShow) || false
    if (visible) {
      if (item.apiDO && item.apiDO.url && item.apiDO.url !== 'null') {
        findUintById(item.elementId).then(
          (pz_res:any) => {
            pz_list[item.elementType] = pz_res
            getMapDataByUrl(item.apiDO.url, params).then((res:any) => {
              layerData.value[item.elementType] = res
              if (pz_res.heatmapDO) {
                const fieldNameEn = JSON.parse(pz_res.heatmapDO.config).timeAccordance || 'bjsj'
                try {
                  if (res && res.length > 0) {
                    res.forEach((sitem:any) => {
                      if (sitem[fieldNameEn]) {
                        sitem.parseDate = Date.parse(sitem[fieldNameEn].split('T')[0])
                      }
                    })
                  }
                  mainmapDom.value?.addFeaturLayer(item, res, { icon: item.elementType }, pz_res)
                } catch (error) {
                  console.log(error)
                }
              } else {
                try {
                  mainmapDom.value?.addFeaturLayer(item, res, { icon: item.elementType }, pz_res)
                } catch (error) {
                  console.log(error)
                }
              }
              // 展示热力
              if (pz_res.showType === 1) {
                pz_res.heat = true
                pz_res.showCluster = !pz_res.heat
                handleHeat(pz_res, true)
              } else if (pz_res.showType === 2) { // 展示聚合
                pz_res.showCluster = true
                pz_res.heat = !pz_res.showCluster
                callbackClusterData(pz_res)
              }
            })
          })
      }
    }
  })
  if (firstLoad) {
    layerListDataCopy.value = JSON.parse(JSON.stringify(layerListData.value))
  }
}
const searchElementType = ref('')
// 搜索框输入时传递搜索的条件及内容
const handleSearchContent = (searchMenu:any, content:any) => {
  // console.log(searchMenu, content) // 传递搜索条件及内容 在此调用地图相关方法
  if (searchMenu.element_type) {
    searchElementType.value = searchMenu.element_type
    try {
      mainmapDom.value?.searchFeature(searchMenu, content)
    } catch (error) {
      console.log(error)
    }
  } else {
    ElMessage({
      type: 'warning',
      message: '请选择搜索图层类型!',
      duration: 2000,
      showClose: true
    })
  }
}
// 查询点击的结果
const handleSearchData = (content:any) => {
  // console.log(content) // 点击搜索结果触发地图事件 在此调用地图定位点的事件
  try {
    mainmapDom.value?.goToFeature(content)
  } catch (error) {
    console.log(error)
  }
}
// 获取地图元素查询返回列表
const getResultList = (res:any) => {
  resultList.value = res
  resultList.value.forEach((element:any) => {
    const pz = pz_list[searchElementType.value]
    if (pz && pz.pointDO && pz.pointDO.icon && pz.pointDO.icon !== '') {
      element.icon = pz.pointDO.icon
    } else {
      element.icon = ''
    }
  })
}

// 获取地图右键点击标绘区域
const openFilter = (res:any) => {
  drawData.value = res
  nextTick(() => {
    if (drawData.value[0] && drawData.value[0].x && drawData.value[0].y) {
      dialogFilterDom.value.filterContainerDom.style.top = drawData.value[0].y + 'px'
      dialogFilterDom.value.filterContainerDom.style.left = drawData.value[0].x + 'px'
      dialogFilterDom.value.filterContainerDom.style.zIndex = String(minIndex.value++)
    }
  })
}

// 点击元素详情弹窗
const openInfoWindow = async (resData:any) => {
  const res = resData.res
  const screePoints = resData.screePoints
  elementData.value = {}
  for (const i in res) {
    if (res[i]) {
      elementData.value[i] = res[i]
    }
  }
  layerId.value = elementData.value.layerIDCODE
  const data = await queryInfoById(layerId.value)
  detailTitle.value = data.detailTitle
  showUserDataDialog.value = true
  nextTick(() => {
    if (screePoints && screePoints.x && screePoints.y) {
      dialogUserDataDom.value.userDataDom.style.top = screePoints.y + 'px'
      dialogUserDataDom.value.userDataDom.style.left = screePoints.x + 'px'
      dialogUserDataDom.value.userDataDom.style.zIndex = String(minIndex.value++)
      dialogUserDataDom.value?.ctlDomLocation()
    }
  })
}

// 关闭详情弹窗
const closeUserDialog = () => {
  showUserDataDialog.value = false
  elementData.value = {}
  mainmapDom.value?.closeHighlight()
}
const closeUserCenterDialog = () => {
  detailShow.value = false
  elementData.value = {}
  mainmapDom.value?.closeHighlight()
}
// 触发删除选中标绘区域
const delectDraw = (unCheckedLayers:any) => {
  if (drawData.value && drawData.value[1]) {
    try {
      mainmapDom.value?.delectGraphic(drawData.value[1], unCheckedLayers)
    } catch (error) {
      console.log(error)
    }
  }
  drawData.value = null
}

// 关闭标绘筛选弹窗
const closeDialog = () => {
  drawData.value = null
  try {
    mainmapDom.value?.closeFilterDialog()
  } catch (error) {
    console.log(error)
  }
}
// 选择标绘范围内的图层
const selectedLayers = (layers:any, ifSelect:boolean) => {
  try {
    if (layers && layers.length > 0 && drawData.value && drawData.value[1]) {
      layers.forEach((item:any) => {
        mainmapDom.value?.featureInDrawGraphic(drawData.value[1], item.elementType, ifSelect)
      })
    }
  } catch (error) {
    console.log(error)
  }
}
// 选择行政区划
const handleAreaSelect = (data:any) => {
  if (data.code) {
    currentAreaCode.value = data.code
    getMapListData()
  }
}

// 获取图层搜索列表
const getLayerSearchList = async () => {
  const res = await elementSearchList()
  layerSearchList.value = res
}
getLayerSearchList()

// 获取标绘列表存储的图形数据
const getDrawList = async () => {
  const res = await queryDrawList()
  mainmapDom.value?.initDrawLyer(res)
  // initDrawLyer(res)
}

// 时间轴返回结果
const timeInterval = (res:any) => {
  try {
    const startTime = Date.parse(res.split(' - ')[0].replaceAll('/', '-'))
    const endTime = Date.parse(res.split(' - ')[1].replaceAll('/', '-'))
    mainmapDom.value?.changeHeatMap(nowHeatLayerId.value, startTime, endTime)
  } catch (error) {
    console.log(error)
  }
}

// 跳转到详情
const toDetail = async (item:any, id:any) => {
  layerId.value = id
  elementData.value = item
  const data = await queryInfoById(id)
  detailShow.value = data.detailType === 1
  detailTitle.value = data.detailTitle

  if (data.detailType === 0) {
    const searchMenu = {
      search1: 'id',
      element_type: item.elementType
    }
    const content = String(item.id)
    const ifSearchDialog = false
    if (searchMenu.element_type) {
      try {
        mainmapDom.value?.searchFeature(searchMenu, content, ifSearchDialog)
      } catch (error) {
        console.log(error)
      }
    }
  }
}
</script>

<script lang="ts">
export default {
  name: 'MapHome'
}
</script>
<style lang="scss" scoped>
.homeMapContainer{
  position: relative;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  .loading{
    position: absolute;
    left: 50%;
    top: 50%;
    width: 4.5rem;
    height: 4.5rem;
    transform: translate(-50%, -50%);
    pointer-events: none;
    z-index: 9;
  }
  .locationDialog{
    position: absolute;
      margin-right: 12px;
      right: 0.1rem;
      top: 0.1rem;
  }
  .search-container {
    .search-dialog {
      position: absolute;
      margin-right: 12px;
      right: 0.1rem;
      top: 2rem;
    }
  }
  .mapComponents{
    position: absolute;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    z-index: 1;
  }
  .heat{
    position: absolute;
    bottom: 0;
    right: 0;
    margin-right: 50px;
    margin-bottom: 40px;
  }
  .mapCtlDom{
    pointer-events: none;
    position: absolute;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    z-index: 9;
  }
  .mapCtlDomItem{
    pointer-events: all;
  }
  .videoDialog{
    width: 40%;
    height: auto;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 11;
  }
  .userDataDialog{
    position: absolute;
    width: 8rem;
    z-index: 11;
  }
  .filterDataDialog{
    position: absolute;
  }

  .detailDialog{
    width: 50%;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 10;
  }
}
</style>
